/************************************************************************
 * The code is owned by mainframer.cn and Shang Tao
 * Without aproval of mainframer.cn and Shang Tao, remove the copyright
 * infomation is regarded invassion of proprietary copyright
 ***********************************************************************/
package com.mr.qa.action;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.net.io.Util;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.action.ActionMessage;
import org.apache.struts.action.ActionMessages;
import org.apache.struts.upload.FormFile;
import org.hibernate.Transaction;

import com.mr.qa.GlobalConfigs;
import com.mr.qa.UserSession;
import com.mr.qa.UserSessionUtil;
import com.mr.qa.GlobalConfigs.UploadFileType;
import com.mr.qa.action.check.DailyAddImageCheck;
import com.mr.qa.action.check.DailyAddQuestionCheck;
import com.mr.qa.action.check.DailyCheck;
import com.mr.qa.bo.Answer;
import com.mr.qa.bo.City;
import com.mr.qa.bo.MrIaskCategoryStatistics;
import com.mr.qa.bo.Question;
import com.mr.qa.bo.QuestionCategory;
import com.mr.qa.bo.ShopArticle;
import com.mr.qa.bo.User;
import com.mr.qa.dao.impl.AnswerDAO;
import com.mr.qa.dao.impl.CityDAO;
import com.mr.qa.dao.impl.QuestionCategoryDAO;
import com.mr.qa.dao.impl.QuestionDAO;
import com.mr.qa.dao.impl.SharedFileDAO;
import com.mr.qa.dao.impl.UserDAO;
import com.mr.qa.dao.impl.UserScoreHistoryConstants;
import com.mr.qa.exception.QaException;
import com.mr.qa.exception.SecurityException;
import com.mr.qa.form.QuestionForm;
import com.mr.qa.util.HibernateSessionFactory;


public class QuestionAction extends BaseAction 
{
    private static final Log logger = LogFactory.getLog(QuestionAction.class);
    
    private final String BOLD_STYLE = "font-weight:bold;";
    private final String COLOR_RED_STYLE = "color:red;";
    private final String COLOR_BLUE_STYLE = "color:blue;";
    
    public ActionForward doAction(ActionMapping mapping, ActionForm form,
                    HttpServletRequest request, HttpServletResponse response) 
                    throws Exception
    {
        //int ibmAlumCategoryId = GlobalConfigs.IBM_ALUM_CATEGORY_ID;
        ActionForward af = null;
        ActionMessages errors = new ActionMessages();
        ActionMessages messages = new ActionMessages();
        UserSession us = null;
        us = UserSessionUtil.getUserSession(request);
        String action = this.getAction(request);
        QuestionForm questionForm = (QuestionForm)form;
        String id = questionForm.getId();
        int qid = 0;
        Integer categoryType = questionForm.getCategoryType();
        if(categoryType == null){
        	if(request.getRequestURI().equals("/life.mrqa")){
        		categoryType = 1;
        	}else if(request.getRequestURI().equals("/tech.mrqa")){
        		categoryType = 2;
        	}
        }
        if(id != null)
        {
            try
            {
                qid = new Integer(id);
            }catch(Exception e)
            {
                logger.error("Question id:"+id+" is not numeric,url="+request.getRequestURL()+"?"+request.getQueryString());
                return mapping.findForward("noquestion");
            }
        }
        int page = questionForm.getPage();
        if(page == 0)page = 1;
        Integer catId = questionForm.getCatId();
        int pageSize = questionForm.getPageSize();
        if(pageSize == 0)
        {
            if(action == null)action = "";
            if(action.indexOf("list") >= 0 || action.indexOf("search") >= 0)
            {
            	if (categoryType != null && categoryType == 1) {
            		if (catId == null)
						pageSize = GlobalConfigs.SIZE_LIFE_LIST;
					else
						pageSize = GlobalConfigs.SIZE_CATEGORY_LIFE_LIST;
				} else if (categoryType != null && categoryType == 2) {
            		if (catId == null)
						pageSize = GlobalConfigs.SIZE_TECH_LIST;
					else
						pageSize = GlobalConfigs.SIZE_CATEGORY_TECH_LIST;
            	}else {
					if (catId == null)
						pageSize = GlobalConfigs.SIZE_QUESTION_LIST;
					else
						pageSize = GlobalConfigs.SIZE_CATEGORY_QUESTION_LIST;
				}
            }
            else if("myquestions".equals(action)) 
            {
                pageSize = 30;   
            }
            else
            {
                pageSize = GlobalConfigs.NUMBER_ANSWER_FOR_VIEW_QUESTION;
            }
        }
        request.setAttribute("pageSize",""+pageSize);
        if("view".equals(action) || "get".equals(action))
        {
            Question question = null;
            if(id == null || id.length() == 0)
            {
                id = questionForm.getQuestionId();
                if(id == null) 
                {
                    //if action=view and id=null for baidu spider
                    index(request,errors);
                    action = "index";
                }
                else 
                {
                    qid = new Integer(id);    
                }
            }
            if(id != null)
            {
                if("view".equals(action))
                    question = view(qid);
                else if("get".equals(action))
                    question = getQuestion(qid);
            }
            if(question == null)
            {
                if(id != null)
                action = "noquestion";
            }
            else
            {
                Boolean isRequieLogin = question.getIsRequireLogin();
                if(!isRequieLogin || (us != null && isRequieLogin))
                {
                	String titleAttribute = question.getTitleAttribute();
                	if(titleAttribute != null && titleAttribute.length() > 0){
                		if(titleAttribute.indexOf(BOLD_STYLE) >= 0){
                			questionForm.setTitleIsBold(true);
                		}
                		if(titleAttribute.indexOf(COLOR_RED_STYLE) >= 0){
                			questionForm.setTitleColor(1);
                		}else if(titleAttribute.indexOf(COLOR_BLUE_STYLE) >= 0){
                			questionForm.setTitleColor(2);
                		}
                	}
                    request.setAttribute("questiono",question);
                    if("Y".equals(question.getMrIaskCategory().getOnlyForAdmin()))//admin
                    {
                        action = "viewa";
                    }
                    else if("T".equals(question.getMrIaskCategory().getOnlyForAdmin()))//research
                    {
                        action = "viewt";
                    }
                    else if("I".equals(question.getMrIaskCategory().getOnlyForAdmin()) 
                    && !question.getMrIaskCategory().getIsTraining())
                    {//internal 2008.3.26 isTraining 2008.12.24 22:28
                        boolean userHasViewRight = false;//2008.07.01
                        if(us != null)
                            if("1".equals(us.getType()) || us.getIsSuper())userHasViewRight = true;
                        if(!userHasViewRight)
                        {
                            errors.add("noright", new ActionMessage("user.noright"));
                            action = "login";
                        }
                    }
                    /*else if(QuestionActionUtility.isUnderMFerClub(question.getMrIaskCategory()))
                    {
                        action = "viewibmalum";//2008.6.12
                    }
                    else if(question.getMrIaskCategory().getIsTraining()) 
                    {
                        action = "viewtraining";//2008.6.12
                    }*/
                    //the below added on Nov 08, 2008
                         String gotoLastPage = request.getParameter("gotoLastPage");
                         if("true".equals(gotoLastPage))
                         {
                             int answersSize = question.getMrIaskAnswers().size();
                             int lastPage = answersSize/GlobalConfigs.NUMBER_ANSWER_FOR_VIEW_QUESTION
                             +((answersSize%GlobalConfigs.NUMBER_ANSWER_FOR_VIEW_QUESTION > 0)?1:0);
                             request.setAttribute("page",""+lastPage);
                         }
                }
                else
                {
                    errors.add("relogin", new ActionMessage("question.view.require.login"));
                    action = "login";
                }
            }
            if (question != null && question.getMrIaskCategory().getType() == 1){
            	CityDAO cityDao = new CityDAO();
                List list = cityDao.findAll();
                request.setAttribute("citiesList", list);
                Set citySet = question.getCities();
                String[] cities = new String[citySet.size()];
                int i = 0;
                for(Iterator it = citySet.iterator(); it.hasNext();){
                	cities[i] = ((City)it.next()).getId() + "";
                	i++;
                }
                questionForm.setCities(cities);
            }
        }/* commented 23 Dec 2008
        else if("get".equals(action))
        {
            Question question;
            question = getQuestion(qid);
            request.setAttribute("questiono",question);
            String gotoLastPage = request.getParameter("gotoLastPage");
            if("true".equals(gotoLastPage))
            {
                int answersSize = question.getMrIaskAnswers().size();
                int lastPage = answersSize/GlobalConfigs.NUMBER_ANSWER_FOR_VIEW_QUESTION
                +((answersSize%GlobalConfigs.NUMBER_ANSWER_FOR_VIEW_QUESTION > 0)?1:0);
                request.setAttribute("page",""+lastPage);
            }
            if("Y".equals(question.getMrIaskCategory().getOnlyForAdmin()))//admin
            {
                action = "viewa";
            }
            else if("T".equals(question.getMrIaskCategory().getOnlyForAdmin()))//research
            {
                action = "viewt";
            }
            else if("I".equals(question.getMrIaskCategory().getOnlyForAdmin()))//internal 2008.3.26
            {
                boolean userHasViewRight = false;//2008.07.01
                if(us != null)
                    if("1".equals(us.getType()) || us.getIsSuper())userHasViewRight = true;
                if(!userHasViewRight)
                {
                    errors.add("noright", new ActionMessage("user.noright"));
                    action = "login";
                }
            }
            else if(question.getMrIaskCategory().getId() == ibmAlumCategoryId)
            {
                action = "viewibmalum";//2008.6.12
            }
            else if(question.getMrIaskCategory().getIsTraining()) 
            {
                action = "viewtraining";//2008.6.12
            }
        }*/
        else if("preadd".equals(action))
        {
            if(us == null)
            {
                errors.add("relogin", new ActionMessage("login.required"));
                action = "login";
            }    
            else
            {
                //if the hours after registration is below GlobalConfigs.HOURS_ADDQUESTION_AFTER_REGISTRATION
                long dif = (new Date().getTime() - us.getRegisterDate().getTime())/3600000;
                if( dif < GlobalConfigs.HOURS_ADDQUESTION_AFTER_REGISTRATION)
                {
                    errors.add("addquestion-limit", new ActionMessage("question.add.limit.userregistration",
                    ""+GlobalConfigs.HOURS_ADDQUESTION_AFTER_REGISTRATION));
                    request.setAttribute("disableSubmit","true");
                }else if(!us.isActive()){
            		errors.add("addquestion-limit", new ActionMessage("user.inactive", ""));
            		request.setAttribute("disableSubmit","true");
            	}
                else if(!("1".equals(us.getType()) || us.getIsSuper()))
                {
                	DailyCheck dailyCheck = new DailyAddQuestionCheck();
                	dailyCheck.init(us.getUserId());
                    boolean canAdd = dailyCheck.check(us.getUserId());
                    if(!canAdd)
                    {
                        errors.add("addquestion-limit", new ActionMessage("question.add.limit.dailynumber",
                        ""+GlobalConfigs.NUMBER_QUESTIONS_A_USER_ONE_DAY));
                        request.setAttribute("disableSubmit","true");
                    }
                }
                CityDAO cityDao = new CityDAO();
                List list = cityDao.findAll();
                request.setAttribute("cities", list);
            }
        }
        else if("add".equals(action))
        {
            boolean userCanAdd = true;
            DailyCheck dailyCheck = new DailyAddQuestionCheck();
            if(us == null)
            {
                errors.add("relogin", new ActionMessage("login.required"));
                action = "login";
                userCanAdd = false;
            }
            //check is active user
            else if(!us.isActive()){
        		errors.add("addquestion-limit", new ActionMessage("user.inactive", ""));
        		action = "preadd";
                userCanAdd = false;
        	}
            else if(!("1".equals(us.getType()) || us.getIsSuper()))
            {
                long dif = (new Date().getTime() - us.getRegisterDate().getTime())/3600000;
                if( dif < GlobalConfigs.HOURS_ADDQUESTION_AFTER_REGISTRATION)
                {
                    errors.add("addquestion-limit", new ActionMessage("question.add.limit.userregistration",
                    ""+GlobalConfigs.HOURS_ADDQUESTION_AFTER_REGISTRATION));
                    action = "preadd";
                    userCanAdd = false;
                }
                else
                {
                	dailyCheck.init(us.getUserId());
                    boolean canAdd = dailyCheck.check(us.getUserId());
                    if(!canAdd)
                    {
                        errors.add("addquestion-limit", new ActionMessage("question.add.limit.dailynumber",
                        ""+GlobalConfigs.NUMBER_QUESTIONS_A_USER_ONE_DAY));
                        action = "preadd";
                        userCanAdd = false;
                    }
                }
            }
            if(userCanAdd)
            {
                String vc = questionForm.getVc();
                if(vc == null)vc = "";
                String vcinSession = UserSessionUtil.getVerificationCodes(request);
                if(vc.length() == 0)
                {
                    errors.add("vc", new ActionMessage("verificationcode.required"));
                    action = "preadd";
                    userCanAdd = false;
                }
                else if(!vc.equals(vcinSession))
                {
                    errors.add("vc", new ActionMessage("verificationcode.error"));
                    action = "preadd";
                    userCanAdd = false;
                }
            }
            //user can add?
                if(userCanAdd)
                {
                    Question question = add(questionForm,us,errors, request.getRemoteAddr());
                    if(errors.size() == 0)
                    {
                        String path = null;
                        if(question.getMrIaskCategory().getType() == 0){
                    		path = "/question.mrqa?action=get&id=!?";
                    	}else if(question.getMrIaskCategory().getType() == 1){
                    		path = "/life.mrqa?action=get&id=!?";
                    	}else if(question.getMrIaskCategory().getType() == 2){
                    		path = "/tech.mrqa?action=get&id=!?";
                    	}
                        path = path.replace("!?",""+question.getId());
                        af = new ActionForward(path);
                        af.setRedirect(true);
                    }
                    else
                    {
                        af = mapping.findForward("preadd");
                    }
                    //to update the number of questions in one day
                    dailyCheck.update(us.getUserId());
                }
        }
        else if("archive".equals(action))
        {
             setType(new Integer(id), "state", "5");//the question can't be answered
              String path = mapping.findForward(action).getPath();
              path = path.replace("!?",id);
              af = new ActionForward(path);
              af.setRedirect(true);
              request.setAttribute("isFromInternal","Y");
        }
        else if("delete".equals(action))
        {
            if(us == null)
            {
                errors.add("relogin", new ActionMessage("login.required"));
                action = "relogin";
            }
            else
            {
                Question question = this.getQuestion(qid);
                User questionUser = question.getMrIaskUser();
                boolean isAuthor = questionUser.getLoginName().equals(us.getLoginName());
                boolean canDelete = false;
                String operatorPermissions = us.getPermissions();
                if(operatorPermissions == null)operatorPermissions = "";
                if("1".equals(us.getType()))
                {
                    canDelete = true;
                }
                else if(us.getIsSuper() && 
                operatorPermissions.indexOf(question.getMrIaskCategory().getId()+",") >= 0)
                {
                    canDelete = true;
                }
                else if(isAuthor)
                {
                    Date postDate = question.getPostDate();
                    Date curDate = new Date();
                    long differ = (curDate.getTime()-postDate.getTime())/1000/60/60;
                    if(differ >= 24)
                    {
                        errors.add("noright", new ActionMessage("user.noright"));
                        action = "error";
                    }
                    else
                    {
                        canDelete = true;
                    }
                }
                if(canDelete)
                {
                	action = "confirmdeletemyquestion";
                    request.setAttribute("canDelete","true");
                    request.setAttribute("questionName",question.getTitle());
                    request.setAttribute("questionHasAnswer",(question.getMrIaskAnswers().size() > 0)?"true":"false");
                }//can delete
                else
                {
                    errors.add("noright", new ActionMessage("user.noright"));
                    action = "error";
                }
            }//us has logined
        }
        else if("deleteafterconfirm".equals(action))
        {
            if(us == null)
            {
                errors.add("relogin", new ActionMessage("login.required"));
                action = "relogin";
            }
            else
            {
                Question question = this.getQuestion(qid);
                User questionUser = question.getMrIaskUser();
                boolean isAuthor = questionUser.getLoginName().equals(us.getLoginName());
                boolean canDelete = false;
                String operatorPermissions = us.getPermissions();
                if(operatorPermissions == null)operatorPermissions = "";
                if("1".equals(us.getType()))
                {
                    canDelete = true;
                }
                else if(us.getIsSuper() && 
                operatorPermissions.indexOf(question.getMrIaskCategory().getId()+",") >= 0)
                {
                    canDelete = true;
                }
                else if(isAuthor)
                {
                    Date postDate = question.getPostDate();
                    Date curDate = new Date();
                    long differ = (curDate.getTime()-postDate.getTime())/1000/60/60;
                    if(differ >= 24)
                    {
                        errors.add("noright", new ActionMessage("user.noright"));
                        action = "error";
                    }
                    else
                    {
                        canDelete = true;
                    }
                }
                String canDeleteConfirm = request.getParameter("canDelete");
                if(!"true".equals(canDeleteConfirm) || !canDelete)
                {
                    errors.add("noright", new ActionMessage("user.noright"));
                    action = "error";
                }
                else
                {
                    String vc = questionForm.getVc();
                    if(vc == null || vc.length() < 4)
                    {
                        errors.add("vc", new ActionMessage("verificationcode.required"));
                        action = "confirmdeletemyquestion";
                    }
                    else
                    {
                        String vcInSession = UserSessionUtil.getVerificationCodes(request);
                        if(vcInSession.equals(vc))
                        {
                            String userType = us.getType();
                            if("0".equals(userType) && us.getIsSuper()) {
                                userType = "1";
                            }
                            Integer deletedQuestionCatId = delete(new Integer(id),userType, us.getUserId());
                            messages.add("deletesuccess", new ActionMessage("question.delete.success",question.getTitle()));
                            String from = request.getParameter("from");
                            if(from == null)from = "";
                            if("admin".equals(from))
                            {
                                String path = "/qcat.mrqa?action=list&id="+deletedQuestionCatId;
                                af = new ActionForward(path);
                                af.setRedirect(true);
                            }
                            else if("mycenter".equals(from))
                            {
                                request.setAttribute("questions",getMyQuestions(us.getUserId(),page,pageSize));
                                action = "myquestions";
                            }
                            else if("".equals(from))
                            {
                            	String path = null;
                            	if(question.getMrIaskCategory().getType() == 0){
                            		path = "/question.mrqa?action=list&catId="+deletedQuestionCatId;
                            	}else if(question.getMrIaskCategory().getType() == 1){
                            		path = "/life.mrqa?action=list&catId="+deletedQuestionCatId;
                            	}else if(question.getMrIaskCategory().getType() == 2){
                            		path = "/tech.mrqa?action=list&catId="+deletedQuestionCatId;
                            	}
                                af = new ActionForward(path);
                                af.setRedirect(true);
                            }
                        }
                        else
                        {
                            errors.add("vc", new ActionMessage("verificationcode.error"));
                            action = "confirmdeletemyquestion";
                        }
                    }
                }
            }
        }
        else if("modify".equals(action))
        {
        	if (!us.isActive()){
        		errors.add("", new ActionMessage("user.inactive"));
        		String path = mapping.findForward("modify-failure").getPath();
				path = path.replace("!?", id);
				af = new ActionForward(path);
        	}
            FormFile file = questionForm.getFile();
            if(file != null && file.getFileSize() > 0)
            {
            	if(!us.getType().equals("1")){
                int fileSize = file.getFileSize();
					if (fileSize > UploadFileType.getMaxSize(UploadFileType.attachment)) {
						errors.add("", new ActionMessage("uploadfile.oversize"));
						// af = mapping.findForward("modify-failure");
						String path = mapping.findForward("modify-failure").getPath();
						path = path.replace("!?", id);
						af = new ActionForward(path);
					}
            	}
            }
            if(errors.size() == 0)
            {
                modify(questionForm,errors);
                String path = mapping.findForward(action).getPath();
                path = path.replace("!?",id);
                af = new ActionForward(path);
                af.setRedirect(true);
                request.setAttribute("isFromInternal","Y");
            }
        }
        else if("setpoll".equals(action))
        {
            if(us == null)
            {
                errors.add("relogin", new ActionMessage("login.required"));
                action = "relogin";
            }
            else
            {
                setType(qid, "poll", "1");
                String path = mapping.findForward(action).getPath();
                path = path.replace("!?",id);
                af = new ActionForward(path);
                af.setRedirect(true);
                request.setAttribute("isFromInternal","Y");
            }    
        }
        else if("setnopoll".equals(action))
        {
            if(us == null)
            {
                errors.add("relogin", new ActionMessage("login.required"));
                action = "relogin";
            }
            else
            {
                setNoPoll(qid);
                String path = mapping.findForward(action).getPath();
                path = path.replace("!?",id);
                af = new ActionForward(path);
                af.setRedirect(true);
                request.setAttribute("isFromInternal","Y");
            }     
        }
        else if("close".equals(action))
        {
            if(us == null)
            {
                errors.add("relogin", new ActionMessage("login.required"));
                action = "relogin";
            }
            else
            {
                String from = request.getParameter("from");                        
                setType(qid, "state", "4");
                if(from == null)
                {
                    String path = mapping.findForward(action).getPath();
                    path = path.replace("!?",id);
                    af = new ActionForward(path);
                    af.setRedirect(true);
                    request.setAttribute("isFromInternal","Y");
                }
                else if("admin".equals(from))
                {
                    Question question = getQuestion(qid);
                    String path = "/qcat.mrqa?action=list&id="+question.getMrIaskCategory().getId();
                    af = new ActionForward(path);
                    af.setRedirect(true);
                    request.setAttribute("isFromInternal","Y");
                }
                else if("mycenter".equals(from))
                {
                    request.setAttribute("questions",getMyQuestions(us.getUserId(),page,pageSize));
                    action = "myquestions";
                }
            }                        
        }
        else if("reopen".equals(action))
        {
            String from = request.getParameter("from");//come from personal center
            if(us == null)
            {
                errors.add("relogin", new ActionMessage("login.required"));
                action = "relogin";
            }
            else
            {
                setType(qid, "state", "0"); 
                if(from == null)//from view question
                {
                    String path = mapping.findForward(action).getPath();
                    path = path.replace("!?",id);
                    af = new ActionForward(path);
                    af.setRedirect(true);
                    request.setAttribute("isFromInternal","Y");
                }    
                else if("admin".equals(from))//from admin
                {
                    Question question = getQuestion(qid);
                    String path = "/qcat.mrqa?action=list&id="+question.getMrIaskCategory().getId();
                    af = new ActionForward(path);
                    af.setRedirect(true);
                }
                else if("mycenter".equals(from))
                {
                    request.setAttribute("questions",getMyQuestions(us.getUserId(),page,pageSize));
                    action = "myquestions";
                }
            }
        }
        else if("vote".equals(action))
        {
            if(us == null)
            {
                errors.add("relogin", new ActionMessage("login.required"));
                action = "relogin";
            }
            else
            {
                if(!us.questionIsVoted(qid))
                {
                    vote(qid,questionForm.getPollItem(),us.getUserId());
                    us.addVotedQuestion(qid);
                }
                else
                {
                    errors.add("vote", new ActionMessage("question.voted"));
                }
                String path = mapping.findForward(action).getPath();
                path = path.replace("!?",id);
                af = new ActionForward(path);
                request.setAttribute("isFromInternal","Y");
            }
        }
        else if("setpollitems".equals(action))
        {
            if(us == null)
            {
                errors.add("relogin", new ActionMessage("login.required"));
                action = "relogin";
            }
            else
            {
                setPollItems(qid,questionForm.getPollItem(),request.getParameterValues("prePollItem"));
                String path = mapping.findForward(action).getPath();
                path = path.replace("!?",id);
                af = new ActionForward(path);
                af.setRedirect(true);
                request.setAttribute("isFromInternal","Y");
            }

        }
        else if("hide".equals(action))
        {
            setType(qid, "state", "3");
        }
        else if("list".equals(action))
        {
          try
          {
            //request.setAttribute("resultSize",countAll(catId));
            //this does not work, in cat is destroyed before list is returned.
            //try another way......
        	if(categoryType == null){
        		categoryType = new Integer(0);
        	}
            Collection list = list(page,pageSize,catId,request,errors,us, categoryType, questionForm);
            //System.out.println("out cat="+cat);
            //request.setAttribute("questionsSize",list.size());//2008.8.31 for google ad on user-layout.jsp and categoryquestions.jsp
            //request.setAttribute("questionsSizePerPage",pageSize);//2008.8.31 for google ad on user-layout.jsp and categoryquestions.jsp
            if(catId == null && categoryType != null){
            	saveInRequest(request,countByType(categoryType),list.size(),pageSize);//2009.10.7
            }
            else{
            	saveInRequest(request,countAll(catId),list.size(),pageSize);//2008.9.10
            }
            request.setAttribute("questions",list);
            
            if (categoryType == 1){
            	getAllCities(request);
            }
            action = getListForward(catId);
            /*
            if(catId != null && catId.intValue() > 0 && catId == ibmAlumCategoryId)
            {
                action = "listibm";
            }
            else if(catId != null && catId.intValue() > 0 && catId == 56)//training 
            {
                action = "listtraining";
            }
            else if(catId != null && catId.intValue() > 0)
            {
                String catKind = this.getQuestionCategoryKind(catId);
                if("Y".equals(catKind))action = "lista";
                else if("T".equals(catKind))action = "listt";
            }*/
          }
          catch(SecurityException se){action = "relogin";}
        }
        else if("qsfornews".equals(action))
        {
            request.setAttribute("questions",list(page,pageSize,null,request,errors,us, null, questionForm));
        }
        else if("recommendedlist".equals(action))
        {
        	if(categoryType == null){
        		categoryType = new Integer(0);
        	}
            try{
            List list = recommendedList(page,pageSize,catId,request,errors,us, categoryType);
            saveInRequest(request,countRecommendedAll(catId, categoryType),list.size(),pageSize);//2008.9.10
            request.setAttribute("questions",list);
            }catch(SecurityException se){action = "relogin";}
            if (categoryType == 1){
            	getAllCities(request);
            }
            action = getListForward(catId);
        }
        else if("complicatedlist".equals(action))
        {
        	if(categoryType == null){
        		categoryType = new Integer(0);
        	}
            try{
            List list = complicatedList(page,pageSize,catId,request,errors,us, categoryType);
            int count = countComplicatedAll(catId, categoryType);
            //logger.info("1 complicatedlist size"+list.size()+" count="+count);            
            saveInRequest(request,count,list.size(),pageSize);//2008.9.10
            request.setAttribute("questions",list);
            }catch(SecurityException se){action = "relogin";}
            if (categoryType == 1){
            	getAllCities(request);
            }
            action = getListForward(catId);
        }
        else if("hotlist".equals(action))
        {
        	if(categoryType == null){
        		categoryType = new Integer(0);
        	}
            try{
            List list = hotList(page,pageSize,catId,request,errors,us, categoryType);
            saveInRequest(request,countHotAll(catId, categoryType),list.size(),pageSize);//2008.9.10
            request.setAttribute("questions",list);
            }catch(SecurityException se){action = "relogin";}
            if (categoryType == 1){
            	getAllCities(request);
            }
            action = getListForward(catId);
        }
        else if("supplement".equals(action))
        {
            if(us == null)
            {
                errors.add("relogin", new ActionMessage("login.required"));
                action = "relogin";
            }
            else
            {
                if(id == null || id.trim().length() == 0)
                {
                    request.setAttribute("questions",list(page,pageSize,catId,request,errors,us, null, questionForm));
                    action = "index";
                }
                else
                {
                    supplement(qid,questionForm.getAddition());                    
                    String path = mapping.findForward(action).getPath();
                    path = path.replace("!?",id);
                    af = new ActionForward(path);
                    af.setRedirect(true);
                    request.setAttribute("isFromInternal","Y");
                }
            }
        }
        else if("myquestions".equals(action))
        {
            if(us == null)
            {
                errors.add("relogin", new ActionMessage("login.required"));
                action = "relogin";
            }    
            else
            {
                Collection questions = getMyQuestions(us.getUserId(),page,pageSize);
                //System.out.println("my questions size="+questions.size());
                request.setAttribute("questions",questions);
                int count = countMyQuestions(us.getUserId());
                //System.out.println("my questions count="+count);
                request.setAttribute("resultSize",count);
            }                
        }
        else if("recommend".equals(action))
        {
            if(us == null)
            {
                errors.add("relogin", new ActionMessage("login.required"));
                action = "relogin";
            }
            else
            {
                //setType(new Integer(id), "state", "1");
                recommend(qid,errors);
                String path = mapping.findForward(action).getPath();
                path = path.replace("!?",id);
                af = new ActionForward(path);
                af.setRedirect(true);
                request.setAttribute("isFromInternal","Y");
            }    
        }
        else if("unrecommend".equals(action))
        {
            if(us == null)
            {
                errors.add("relogin", new ActionMessage("login.required"));
                action = "relogin";
            }
            else
            {
                //setType(new Integer(id), "state", "0");
                unrecommend(qid,errors);
                String path = mapping.findForward(action).getPath();
                path = path.replace("!?",id);
                af = new ActionForward(path);
                af.setRedirect(true);
                request.setAttribute("isFromInternal","Y");
            }    
        }
        else if("complicate".equals(action))
        {
                if(us == null)
                {
                    errors.add("relogin", new ActionMessage("login.required"));
                    action = "relogin";
                }
                else
                {
                    //setType(new Integer(id), "state", "2");//recommend state?
                    complicate(qid,errors);
                    String path = mapping.findForward(action).getPath();
                    path = path.replace("!?",id);
                    af = new ActionForward(path);
                    af.setRedirect(true);
                    request.setAttribute("isFromInternal","Y");
                }    
        }
        else if("uncomplicate".equals(action))
        {
            if(us == null)
            {
                errors.add("relogin", new ActionMessage("login.required"));
                action = "relogin";
            }
            else
            {
                //setType(new Integer(id), "state", "0");//recommend state?
                uncomplicate(qid,errors);
                String path = mapping.findForward(action).getPath();
                path = path.replace("!?",id);
                af = new ActionForward(path);
                af.setRedirect(true);
                request.setAttribute("isFromInternal","Y");
            }    
        }
        else if("search".equals(action))
        {
        	if(categoryType == null){
        		categoryType = new Integer(0);
        	}
            String title = questionForm.getTitle();
            if(title == null || title.length() == 0)
            {
                List list = list(page,pageSize,null,request,errors,us, categoryType, questionForm);
                saveInRequest(request,countAll(null),list.size(),pageSize);//2008.9.10
                request.setAttribute("questions",list);
            }
            else
            {
                List list = searchQuestionsByTitle(page,pageSize,questionForm.getTitle(), categoryType);
                saveInRequest(request,countQuestionsByTitle(title, categoryType),list.size(),pageSize);//2008.9.10
                request.setAttribute("questions",list);
            }
        }
        else if("deletefile".equals(action))//delete the file associated with the question
        {
            deleteQuestionFile(qid);
            String path = mapping.findForward(action).getPath();
            path = path.replace("!?",""+id);
            af = new ActionForward(path);
            af.setRedirect(true);
        }
        else if("changecat".equals(action))//delete the file associated with the question
        {
            Question question = this.changeCategory(questionForm,us.getUserId());
            String path = null;
            if(question.getMrIaskCategory().getType() == 0){
        		path = "/question.mrqa?action=get&id=!?";
        	}else if(question.getMrIaskCategory().getType() == 1){
        		path = "/life.mrqa?action=get&id=!?";
        	}else if(question.getMrIaskCategory().getType() == 2){
        		path = "/tech.mrqa?action=get&id=!?";
        	}
            path = path.replace("!?",""+id);
            af = new ActionForward(path);
            af.setRedirect(true);
        }
        else if("pretop".equals(action))
        {
            Question question;
            if(id == null || id.length() == 0)
            {
                id = questionForm.getQuestionId();
                qid = new Integer(id);
            }
            question = getQuestion(qid);
            if(question == null)
            {
                action = "noquestion";
            }
            else
            {
                request.setAttribute("questiono",question);
            }
        }
        else if("top".equals(action))
        {
            top(qid,questionForm.getTopLevel(),errors);
            String path = mapping.findForward(action).getPath();
            path = path.replace("!?",""+id);
            af = new ActionForward(path);
            af.setRedirect(true);
        }
        else if("requirelogin".equals(action))//2008.4.11
        {
            requireLogin(qid);
            String path = mapping.findForward(action).getPath();
            path = path.replace("!?",""+id);
            af = new ActionForward(path);
            af.setRedirect(true);
        }
        else if("expire".equals(action))//delete the file associated with the question
        {
            switchExpired(qid);
            String path = mapping.findForward(action).getPath();
            path = path.replace("!?",""+qid);
            af = new ActionForward(path);
            af.setRedirect(true);
        }
        else if("index".equals(action))
        {
            index(request,errors);
            //LoginUtil.setDisplayUserMessages(request);
        }
        else if("lock".equals(action))
        {
            if(super.checkAdminRight(us))
            {
                this.lock(qid);
            }
            else
            {
                errors.add("noright", new ActionMessage("user.noright"));
            }
            //read the question
            String path = mapping.findForward("expire").getPath();
            path = path.replace("!?",""+qid);
            af = new ActionForward(path);
            af.setRedirect(true);
        }
        else if("setasactivity".equals(action))
        {
            if(super.checkAdminRight(us))
            {
                this.setAsActivity(qid);
            }
            else
            {
                errors.add("noright", new ActionMessage("user.noright"));
            }
            //read the question
            String path = mapping.findForward("expire").getPath();
            path = path.replace("!?",""+qid);
            af = new ActionForward(path);
            af.setRedirect(true);
        }
        else if("uploadImage".equals(action))
        {
        	boolean canUpload = true;
        	request.setAttribute("imageIn", questionForm.getImageIn());
        	request.setAttribute("imageArea", questionForm.getImageArea());
        	
        	DailyCheck dailyCheck = new DailyAddImageCheck();
        	
        	if (us != null){
        		if (!("1".equals(us.getType()) || us.getIsSuper())) {
        			dailyCheck.init(us.getUserId());
    				if (!dailyCheck.check(us.getUserId())) {
    					messages.add("addquestion-limit", 
    							new ActionMessage("image.add.limit.dailynumber", 
    									""+ GlobalConfigs.NUMBER_IMAGE_A_USER_ONE_DAY));
    					request.setAttribute("imagePath", "limit");
    					canUpload = false;
    				}
    			}
    			if (canUpload) {
    				if (questionForm.getImage() != null) {
    					String newFilePath = uploadImageFile(questionForm, messages);
    					if(!newFilePath.equals("error")){
    						dailyCheck.update(us.getUserId());
    					}
    					request.setAttribute("imagePath", newFilePath.replace('\\','/'));
    				}
    			}
        	}else{
        		request.setAttribute("imagePath", "limit");
        		messages.add("error", new ActionMessage("login.required"));
        	}
        }
        else
        {
            action = "index";
            index(request,errors);
        }
        if(af == null)
        {
        	if("preadd".equals(action)){
        		CityDAO cityDao = new CityDAO();
                List list = cityDao.findAll();
                request.setAttribute("cities", list);
        	}
            af = mapping.findForward(action);
        }
        if(errors.size() > 0)
        {
            saveErrors(request, errors);
            if(af.getRedirect())
            saveErrors(request.getSession(), errors);
        }
        if(messages.size() > 0)
        {
            saveMessages(request, messages);
            if(af.getRedirect())
            saveMessages(request.getSession(), messages);
        }
        return af;
    }
    
    private void saveInRequest(HttpServletRequest request,int totalSize,int listSize,int sizePerPage)
    {
        request.setAttribute("resultSize",totalSize);
        request.setAttribute("pageSize",sizePerPage);
        request.setAttribute("questionsSize",listSize);
        request.setAttribute("questionsSizePerPage",sizePerPage);
    }
    
    private String getListForward(Integer catId) throws QaException
    {
        String action = "list";
        if(catId == null)return action;
        QuestionCategory cat = this.getQuestionCategory(catId);
        if(QuestionActionUtility.isUnderMFerClub(cat))
        {
            action = "listibm";
        }
        /*
        else if(catId == 56)//training
        {
            action = "listtraining";
        }*/
        else
        {
            String catKind = this.getQuestionCategoryKind(cat);
            if("Y".equals(catKind))action = "lista";
            else if("T".equals(catKind))action = "listt";
        }
        
        return action;
    }
    
    /*
     * set/unset the question to the state which only signon user can view
     */
    private void requireLogin(Integer questionId) throws QaException
    {
        Transaction tx = null;
        try
        {
            tx = HibernateSessionFactory.getSession().beginTransaction();
            QuestionDAO questionDAO = new QuestionDAO();
            Question question = questionDAO.findById(questionId);
            if(!question.getIsRequireLogin())
            {
                question.setIsRequireLogin(true);
            }
            else
            {
                question.setIsRequireLogin(false);
            }
            questionDAO.update(question);
            tx.commit();
        }
        catch(Exception e)
        {
            tx.rollback();
            throw new QaException(e);
        }
        finally 
        {
            HibernateSessionFactory.closeSession();
        }                    
        
    }
    
    /**
     * delete the file associated with the question
     * @param questionId
     * @return
     * @throws QaException
     */
    private int deleteQuestionFile(Integer questionId) throws QaException
    {
        Transaction tx = null;
        int returnValue = 0;
        try
        {
            tx = HibernateSessionFactory.getSession().beginTransaction();
            QuestionDAO questionDAO = new QuestionDAO();
            Question question = questionDAO.findById(questionId);
            String filePath = question.getFile();
            /*
            UploadedFileDAO uploadedFileDAO = new UploadedFileDAO();
            UploadedFile uploadedFile = uploadedFileDAO.findById("q"+questionId);
            if(uploadedFile != null) 
                uploadedFileDAO.delete(uploadedFile);
            */
            if(filePath != null && filePath.length() > 0)
            {
                try
                {
                    String phisicalFileDirStr = getPhisicalUploadedFileDir();
                    String phisicalFile = phisicalFileDirStr+filePath;
                    File file = new File(phisicalFile);
                    file.delete();
                }
                catch(Exception e)
                {
                    logger.debug("deleteQuestionFile ex:"+e);
                }
                question.setFileName("");
                question.setFile("");
                questionDAO.update(question);
            }
            tx.commit();
            returnValue = 1;
        }
        catch(Exception e)
        {
            throw new QaException(e);
        }
        finally 
        {
            HibernateSessionFactory.closeSession();
        }                    
        return returnValue;
    }


    private int countRecommendedAll(Integer catId, Integer categoryType) throws QaException
    {
        Transaction tx = null;
        try
        {
            int count = 0;
            tx = HibernateSessionFactory.getSession().beginTransaction();
            QuestionDAO questionDAO = new QuestionDAO();
            if(catId == null)
                count = questionDAO.countRecommendedAll(categoryType);
            else
            {
                QuestionCategoryDAO categoryDAO = new QuestionCategoryDAO();
                QuestionCategory category = categoryDAO.findById(catId);
                count = questionDAO.countAllRecommendedQuestionsForAQuestionCategory(category);
            }
            tx.commit();
            return count;
        }
        catch(Exception e)
        {
            throw new QaException(e);
        }
        finally 
        {
            HibernateSessionFactory.closeSession();
        }                    
    }



    private int countComplicatedAll(Integer catId, Integer categoryType) throws QaException
    {
        Transaction tx = null;
        try
        {
            int count = 0;
            tx = HibernateSessionFactory.getSession().beginTransaction();
            QuestionDAO questionDAO = new QuestionDAO();
            if(catId == null)
                count = questionDAO.countComplicatedAll(categoryType);
            else
            {
                QuestionCategoryDAO categoryDAO = new QuestionCategoryDAO();
                QuestionCategory category = categoryDAO.findById(catId);
                count = questionDAO.countAllComplicatedQuestionsForAQuestionCategory(category);
            }
            tx.commit();
            return count;
        }
        catch(Exception e)
        {
            throw new QaException(e);
        }
        finally 
        {
            HibernateSessionFactory.closeSession();
        }                    
    }


    private int countHotAll(Integer catId, Integer categoryType) throws QaException
    {
        Transaction tx = null;
        try
        {
            int count = 0;
            tx = HibernateSessionFactory.getSession().beginTransaction();
            QuestionDAO questionDAO = new QuestionDAO();
            if(catId == null)
                count = questionDAO.countHotAll(categoryType);
            else
            {
                QuestionCategoryDAO categoryDAO = new QuestionCategoryDAO();
                QuestionCategory category = categoryDAO.findById(catId);
                count = questionDAO.countAllHotQuestionsForAQuestionCategory(category);
            }
            tx.commit();
            return count;
        }
        catch(Exception e)
        {
            throw new QaException(e);
        }
        finally 
        {
            HibernateSessionFactory.closeSession();
        }                    
    }

    private int countAll(Integer catId) throws QaException
    {
    	if(catId == null)return countAll();
        Transaction tx = null;
        try
        {
            int count = 0;
            tx = HibernateSessionFactory.getSession().beginTransaction();
            QuestionDAO questionDAO = new QuestionDAO();
            QuestionCategoryDAO categoryDAO = new QuestionCategoryDAO();
            QuestionCategory category = categoryDAO.findById(catId);
            count = questionDAO.countAllQuestionsForAQuestionCategory(category);
            tx.commit();
            return count;
        }
        catch(Exception e)
        {
            throw new QaException(e);
        }
        finally 
        {
            HibernateSessionFactory.closeSession();
        }   
    }
    
    private int countByType(Integer categoryType)throws QaException{
    	Transaction tx = null;
        try
        {
            int count = 0;
            tx = HibernateSessionFactory.getSession().beginTransaction();
            QuestionDAO questionDAO = new QuestionDAO();
            if(categoryType != null){
            	count = questionDAO.countByType(categoryType);
            }else{
            	count = questionDAO.countAll();
            }
            tx.commit();
            return count;
        }
        catch(Exception e)
        {
            throw new QaException(e);
        }
        finally 
        {
            HibernateSessionFactory.closeSession();
        }  
    }

    private int countAll() throws QaException
    {
    	Transaction tx = null;
        try
        {
            int count = 0;
            tx = HibernateSessionFactory.getSession().beginTransaction();
            QuestionDAO questionDAO = new QuestionDAO();
            count = questionDAO.countAll();
            tx.commit();
            return count;
        }
        catch(Exception e)
        {
            throw new QaException(e);
        }
        finally 
        {
            HibernateSessionFactory.closeSession();
        }  
    }    


    private int countQuestionsByTitle(String title, Integer categoryType) throws QaException
    {
        Transaction tx = null;
        try
        {
            int count = 0;
            tx = HibernateSessionFactory.getSession().beginTransaction();
            QuestionDAO questionDAO = new QuestionDAO();
            count = questionDAO.countQuestionsByTitle(title, categoryType);
            tx.commit();
            return count;
        }
        catch(Exception e)
        {
            throw new QaException(e);
        }
        finally 
        {
            HibernateSessionFactory.closeSession();
        }                    
    }    
    
    private List searchQuestionsByTitle(int page,int pageSize,String title, Integer categoryType) throws QaException
    {
        Transaction tx = null;
        try
        {
            List questions = null;
            tx = HibernateSessionFactory.getSession().beginTransaction();
            QuestionDAO questionDAO = new QuestionDAO();
            questionDAO.setPage(page,pageSize);
            questions = questionDAO.findQuestionsByTitle(title, categoryType);
            tx.commit();
            return questions;
        }
        catch(QaException e)
        {
            if(tx != null) 
              tx.rollback();
            throw e;
        }
        catch(Exception e)
        {
            throw new QaException(e);
        }
        finally 
        {
            HibernateSessionFactory.closeSession();
        }                    
    }
    
    
    /**
     * set the question as 0 state, its answers as "0"
     * @param questionId
     * @return
     * @throws QaException
     */
    private void setNoPoll(Integer questionId) throws QaException
    {
        QuestionDAO questionDAO = new QuestionDAO();
        AnswerDAO answerDAO = new AnswerDAO();
        Transaction tx = null;
        try
        {
            tx = HibernateSessionFactory.getSession().beginTransaction();
            Question question = questionDAO.findById(questionId);
            if("1".equals(question.getIsPoll()))
            {
                question.setIsPoll("0");
                questionDAO.update(question);
            }
            else
            {
                return;
            }
            Collection answers = question.getMrIaskAnswers();
            Iterator ite = answers.iterator();
            Answer answer;
            while(ite.hasNext())
            {
                answer = (Answer)ite.next();
                if("1".equals(answer.getState()))
                {
                    answer.setState("0");
                    answer.setPollCount(new Integer(0));
                    answerDAO.update(answer);
                }
            }
            tx.commit();
        }
        catch(Exception e)
        {
            if(tx != null) 
              tx.rollback();
            throw new QaException(e);
        }
        finally 
        {
            HibernateSessionFactory.closeSession();
        }        
    }
    private String getQuestionCategoryKind(QuestionCategory cat)
    {
        return cat.getOnlyForAdmin();
    }

    private QuestionCategory getQuestionCategory(Integer catId) throws QaException
    {
        if(catId == null)return null;
        Transaction tx = null;
        try
        {
            QuestionCategory qCategory = null;
            tx = HibernateSessionFactory.getSession().beginTransaction();
            QuestionCategoryDAO questionCatDAO = new QuestionCategoryDAO();
            qCategory = questionCatDAO.findById(catId);
            tx.commit();
            return qCategory;
        }
        catch(Exception e)
        {
            if(tx != null)
              tx.rollback();
            throw new QaException(e);
        }
        finally
        {
            HibernateSessionFactory.closeSession();
        }
    }


    private String getQuestionCategoryKind(Integer catId) throws QaException
    {
        Transaction tx = null;
        try
        {
            QuestionCategory qCategory = null;
            tx = HibernateSessionFactory.getSession().beginTransaction();        
            QuestionCategoryDAO questionCatDAO = new QuestionCategoryDAO();
            qCategory = questionCatDAO.findById(catId);
            tx.commit();
            return qCategory.getOnlyForAdmin();
        }
        catch(Exception e)
        {
            if(tx != null) 
              tx.rollback();
            throw new QaException(e);
        }
        finally 
        {
            HibernateSessionFactory.closeSession();
        }        
    }
    
    /**
     * retrieve the question by id
     * @param questionId
     * @return
     * @throws QaException
     */
    private Question getQuestion(Integer questionId) throws QaException
    {
        Question question = null;
        Transaction tx = null;
        try
        {
            tx = HibernateSessionFactory.getSession().beginTransaction();        
            QuestionDAO questionDAO = new QuestionDAO();
            question = questionDAO.findById(questionId);
            question.getMrIaskComments().size();
            tx.commit();
        }
        catch(Exception e)
        {
            if(tx != null) 
              tx.rollback();
            throw new QaException(e);
        }
        finally 
        {
            HibernateSessionFactory.closeSession();
        }        
        return question;        
    }
    
    /**
     * @param questionId
     * @param pollItem
     * @return Question
     * @throws QaException
     */
    private void setPollItems(Integer questionId,String[] pollItem,String[] prePollItem) throws QaException
    {
        if(questionId == null)throw new QaException("Question ID required");
        Transaction tx = null;
        try
        {
            String pollItemsStr = "";
            if(pollItem != null && pollItem.length > 0)
            {
                for(int i=0;i<pollItem.length;i++)
                {
                    pollItemsStr = pollItemsStr+","+pollItem[i];
                }    
            }
            String prePollItemsStr = "";
            if(prePollItem != null && prePollItem.length > 0)
            {
                for(int i=0;i<prePollItem.length;i++)
                {
                    prePollItemsStr = prePollItemsStr+","+prePollItem[i];
                }    
            }
            
            //logger.info("pollItemsStr="+pollItemsStr);
            QuestionDAO questionDAO = new QuestionDAO();
            AnswerDAO answerDAO = new AnswerDAO();
            tx = HibernateSessionFactory.getSession().beginTransaction();
            Question question = questionDAO.findById(questionId);
            Collection answers = question.getMrIaskAnswers();
            Iterator ite = answers.iterator();
            Answer answer;
            int id;
            String state;
            /**
             * 
             * 1,preseleted,selected no change
             * 1,preselected,unselected change to no pollitem
             * 1,unpreselected,* no change
             * 
             * 0,*,selected change to pollitem
             * 0,*,
             */
            while(ite.hasNext())
            {
                answer = (Answer)ite.next();
                id = answer.getId().intValue();
                state = answer.getState();
                if("1".equals(state))
                {
                    if(prePollItemsStr.indexOf(",s"+id) >= 0)
                    {
                        if(pollItemsStr.indexOf(","+id) >= 0)
                        {
                            //no change
                        }
                        else
                        {
                            answer.setState("0");
                            answerDAO.update(answer);
                        }
                    }
                    else
                    {
                        
                    }
                }
                else if("0".equals(state))
                {
                    if(pollItemsStr.indexOf(","+id) >= 0)
                    {
                        answer.setState("1");
                        answerDAO.update(answer);
                    }    
                }
            }
            tx.commit();
        }
        catch(Exception e)
        {
            if(tx != null) 
              tx.rollback();
            throw new QaException(e);
        }
        finally 
        {
            HibernateSessionFactory.closeSession();
        }        
    }
        
    /**
     * vote
     * @param questionId
     * @param pollItem
     * @return Question
     * @throws QaException
     */
    private void vote(Integer questionId,String[] pollItem,Integer userId) throws QaException
    {
        if(questionId == null)throw new QaException("Question ID required");
        Transaction tx = null;
        try
        {
            AnswerDAO answerDAO = new AnswerDAO();        
            tx = HibernateSessionFactory.getSession().beginTransaction();        
            if(pollItem != null && pollItem.length > 0)
            {
                String item;
                Answer answer;
                for(int i=0;i<pollItem.length;i++)
                {
                    item = pollItem[i];
                    answer = answerDAO.findById(new Integer(item));
                    answer.setPollCount(new Integer(answer.getPollCount().intValue()+1));
                    answerDAO.update(answer);
                }
                answerDAO.addScoreHistory(userId,questionId,"","vote","vote for this question");
            }    
            tx.commit();
        }
        catch(Exception e)
        {
            if(tx != null) 
              tx.rollback();
            throw new QaException(e);
        }
        finally 
        {
            HibernateSessionFactory.closeSession();
        }        
    }
    //viewd by self
    private int countMyQuestions(Integer userId) throws QaException
    {
        Transaction tx = null;
        try
        {
            int count = 0;
            tx = HibernateSessionFactory.getSession().beginTransaction();
            QuestionDAO questionDAO = new QuestionDAO();
            count = questionDAO.countMyQuestions(userId);
            tx.commit();
            return count;
        }
        catch(Exception e)
        {
            throw new QaException(e);
        }
        finally 
        {
            HibernateSessionFactory.closeSession();
        }                    
    }    


    /**
     * returns all questions owned by the user
     */
    private Collection getMyQuestions(Integer myId, int page,int pageSize) throws QaException
    {
        Transaction tx = null;
        try
        {
            QuestionDAO questionDAO = new QuestionDAO();
            questionDAO.setPage(page,pageSize);
            return questionDAO.findMyQuestions(myId);
        }    
        catch(Exception e)
        {
            if(tx != null) 
              tx.rollback();
            throw new QaException(e);
        }
        finally 
        {
            HibernateSessionFactory.closeSession();
        }        
            
    }

    public Question view(Integer id) throws QaException
    {
        QuestionDAO questionDAO = new QuestionDAO();
        Transaction tx = null;
        Question question = null;
        try
        {
            tx = HibernateSessionFactory.getSession().beginTransaction();
            question = questionDAO.findById(id);
            question.setViewCount(new Integer(question.getViewCount().intValue()+1));
            questionDAO.update(question);
            question.getMrIaskComments().size();
            tx.commit();
        }
        catch(NullPointerException npe)
        {
            if(tx != null) 
            tx.rollback();
            return null;
        }
        catch(Exception e)
        {
            throw new QaException("while viewing question id="+id+" find "+e);
        }
        finally
        {
            HibernateSessionFactory.closeSession();  
        }
        return question;                
    }
	
    private void supplement(Integer questionId,String addition) throws QaException
    {
        Transaction tx = null;
        try 
        {
            QuestionDAO questionDAO = new QuestionDAO();        
            tx = HibernateSessionFactory.getSession().beginTransaction();
            Question question = questionDAO.findById(questionId);
            question.setAddition(addition);
            //question.setPostDate(new Date());
            //question.setChangeDate(new Date());
            questionDAO.update(question);
            tx.commit();
        }
        catch(Exception e)
        {
            if(tx != null)tx.rollback();
            throw new QaException(e);
        }
        finally
        {
            HibernateSessionFactory.closeSession();  
        }
    }
        
    /**
     * 
     * @param questionId
     * @param userType the type of the user who executes the deletetion
     * @return
     * @throws QaException
     */
    public Integer delete(Integer questionId,String userType, Integer userId) throws QaException
    {
        Transaction tx = null;
        Integer questionCategoryId;
        try
        {
            QuestionDAO questionDAO = new QuestionDAO();            
            QuestionCategoryDAO categoryDAO = new QuestionCategoryDAO();
            tx = HibernateSessionFactory.getSession().beginTransaction();
            Question question = questionDAO.findById(questionId);
            Set<Answer> answers = question.getMrIaskAnswers();
            if(answers.size() > 0) 
            {
                User answerUser = null;
                for(Answer answer:answers) {
                    answerUser = answer.getMrIaskUser();
                    if(answerUser != null) {
                        questionDAO.addScoreHistory(answerUser,
                        answer.getId(),"",UserScoreHistoryConstants.USER_SCORE_HISTORY_DELETE_ANSWER_BY_QUESTION
                        ,"related question "+questionId+" deleted by "+("1".equals(userType)?"admin":"owner"));
                    }
                }
            }
            QuestionCategory category = question.getMrIaskCategory();
            MrIaskCategoryStatistics mics = null;
            mics = category.getMrIaskCategoryStatistics();
            int count = mics.getTotal();
            if(count > 0)
            {
                mics.setTotal(mics.getTotal()-1);
                categoryDAO.update(category);
            }
            questionCategoryId = question.getMrIaskCategory().getId();
            if("5".equals(question.getState()) || "1".equals(question.getState())){
            	questionDAO.addScoreHistory(question.getMrIaskUser(), questionId,question.getTitle(), "unrecommend", "Question" + questionId +  "is deleted");
            }
            questionDAO.delete(question);
            if("1".equals(userType))
                questionDAO.addScoreHistory(question.getMrIaskUser(),
                question.getId(),question.getTitle(),UserScoreHistoryConstants.
                USER_SCORE_HISTORY_DELETE_QUESTION_BY_ADMIN,"delete question by admin");
            else
                questionDAO.addScoreHistory(question.getMrIaskUser(),
                question.getId(),question.getTitle(),
                UserScoreHistoryConstants.USER_SCORE_HISTORY_DELETE_QUESTION_BY_SELF
                ,"delete question by self");
            try
            {
                String fileName = "";            
                fileName = question.getFileName();
                String fileBytesName = question.getFile();
                if(fileName == null)fileName = "";
                if(fileName.length() > 0)
                {
                    /*
                    UploadedFileDAO ufDAO = new UploadedFileDAO();
                    UploadedFile uf = ufDAO.findById("q"+questionId);
                    ufDAO.delete(uf);
                    */
                    String phisicalFileDirStr = getPhisicalUploadedFileDir();
                    String phisicalFile = phisicalFileDirStr+File.separator+fileBytesName;
                    File oldFile = new File(phisicalFile);
                    oldFile.delete();
                }
            }
            catch(Exception fe)
            {
                logger.error(fe);
            }
            tx.commit();
        }
        catch(Exception e)
        {
            if(tx != null)tx.rollback();
            throw new QaException(e);
        }
        finally
        {
            HibernateSessionFactory.closeSession();  
        }
        return questionCategoryId;
    }
    
    
    /**
     * return the id of newly added question,if error, return null
     * @param form QuestionForm
     * @param userId
     * @return id of the new question
     * @throws QaException
     */
    public Question add(QuestionForm form,UserSession us,ActionMessages errors, String userIP) throws QaException
    {
    	Question question = null;
        Transaction tx = null;
        try
        {
            FormFile file = form.getFile();        
            String fName = "";
            if(file != null)
            {
                fName = file.getFileName();
                if (!us.getType().equals("1")) {
					int fileSize = file.getFileSize();
					if (fileSize > UploadFileType.getMaxSize(UploadFileType.attachment)) {
						errors.add("", new ActionMessage("uploadfile.oversize"));
						return null;
					}
				}
            }
            String title = form.getTitle();
            String content = form.getContent();
            String addition = form.getAddition();
            String reference = form.getReference();
            Integer catId = form.getCatId();
            String[] cities = form.getCities(); 
            String email = form.getEmail();
            String state = "0";
            String poll = "0";
            Integer viewCount = 0;
            Date date = new Date();
            //Integer anonymous = form.getAnonymous();
            QuestionDAO questionDAO = new QuestionDAO();
            UserDAO userDAO = new UserDAO();
            QuestionCategoryDAO categoryDAO = new QuestionCategoryDAO();
            tx = HibernateSessionFactory.getSession().beginTransaction();
            question = new Question();
            question.setTitle(title);
            question.setContent(content);
            question.setAddition(addition);
            question.setReference(reference);
            question.setEmail(email);
            question.setState(state);
            question.setIsPoll(poll);
            QuestionCategory category = categoryDAO.findById(catId);
            question.setMrIaskCategory(category);
            Integer userId = us.getUserId();
            User user = userDAO.findById(userId);
            question.setMrIaskUser(user);
            //question.setIsAnonymous(anonymous);
            question.setViewCount(viewCount);
            question.setPostDate(date);
            question.setChangeDate(date);
            question.setIsRequireLogin(form.getIsRequireLogin());
            question.setAnonymoususerIP(userIP);
            String titleAttribute = setTitleStyle(form.isTitleIsBold(), form.getTitleColor());
            question.setTitleAttribute(titleAttribute);
            if (cities != null && cities.length > 0){
            	Set citiesSet = new HashSet();
            	for(int i = 0; i < cities.length; i++){
            		City city = new City();
            		city.setId(Integer.valueOf(cities[i]));
            		citiesSet.add(city);
            	}
            	question.setCities(citiesSet);
            }
            MrIaskCategoryStatistics mics = null;
            mics = category.getMrIaskCategoryStatistics();
            if(mics == null)
            {
                mics = new MrIaskCategoryStatistics();
                mics.setMrIaskCategory(category);
                category.setMrIaskCategoryStatistics(mics);
                mics.setCategoryType("Q");
                mics.setTotal(1+category.getMrIaskQuestions().size());
            }
            else
            {
                mics.setTotal(1+mics.getTotal());
            }
            question.setFileName("");
            question.setFile("");
            //persist
            questionDAO.save(question);
            categoryDAO.update(category);
            //adding a question under admin category does not add score
            //adding a question under ad category does not add score 2009.1.13
            if("N".equals(category.getOnlyForAdmin()))
            {
                questionDAO.addScoreHistory(user,question.getId(),question.getTitle(),"newquestion","add question");
            }
            else if("T".equals(category.getOnlyForAdmin()))
            {
                question.setIsPoll("1");//the question is a top defaultly set as poll question
                question.setState("4");//newly added topic is set as hided(current close)
            }
            if(fName.length() > 0 )
            {
                String newFilePath = uploadFile(file, UploadFileType.attachment, errors);
                if(newFilePath != null)
                {
                    question.setFileName(fName);
                    question.setFile(newFilePath);
                }
            }
            //id = question.getId();
            tx.commit();
        }
        catch(QaException qe)
        {
            logger.error("add question QaException:"+qe);
        }
        catch(Exception e)
        {
            if(tx != null)tx.rollback();
            logger.error("add question Exception:"+e);            
            throw new QaException(e);
        }
        finally
        {
            HibernateSessionFactory.closeSession();  
        }
        return question;
    }
//checkIfFileExist
    
    /**
     * upload files
     * @param fileType 1: attachment 2: image
     */
    public String uploadFile(FormFile file, UploadFileType uploadFile, ActionMessages errors) throws QaException
    {
        if(file == null)return null;
        String fileName = file.getFileName();
        if(fileName == null || fileName.length() == 0)return null;
        String newFilePath = "";
        try
        {
            if(checkIfFileExist(fileName))
            {
                errors.add("",new ActionMessage("sharedfile.exist",fileName));
                return null;
            }
            InputStream in = file.getInputStream();
            String yearMonthDayPath = checkAndBuildYearMonthDayDir();// /yyyy/mm/dd
            String dirPath = getPhisicalUploadedFileDir(uploadFile)+yearMonthDayPath;// /root/sharedfile/yyyy/mm/dd
            File dir = new File(dirPath);
            if(!dir.exists()){
            	dir.mkdirs();
            }
            String phisicalFile = "";
            phisicalFile = dirPath+File.separator+fileName;
            newFilePath = yearMonthDayPath+"/"+fileName;// /yyyy/mm/dd/file.ext
            OutputStream out = new FileOutputStream(phisicalFile);
            Util.copyStream(in, out);
            in.close();
            out.close();
        }
        catch(Exception e)
        {
            errors.add("",new ActionMessage("uploadfile.failure",fileName));
            logger.error("add share file into dir exception:"+e);
            throw new QaException(e);
        }
        return newFilePath;
    }
    
    private String getDateTimeString(int questionId)
    {
        Date currentDate = new Date();
        SimpleDateFormat bartDateFormat = new SimpleDateFormat("yyyy-MM-dd-hh-ss-mm"); 
        return bartDateFormat.format(currentDate)+"_"+questionId+"_";
    }
    
    //   /userid/yyyy-mm-dd-hh-ss-mm/
    private String makePhisicalFilePath(int userId,int questionId)
    {
        String phisicalFilePath = File.separator+userId+File.separator+getDateTimeString(questionId)+File.separator;
        return phisicalFilePath;
    }
    
    /**
     * @param questionForm QuestionForm
     * @param errors ActionMessages
     * @return
     * @throws QaException
     */
    public void modify(QuestionForm questionForm,ActionMessages errors) throws QaException
    {
        Transaction tx = null;
        try
        {
            QuestionDAO questionDAO = new QuestionDAO();
            tx = HibernateSessionFactory.getSession().beginTransaction();
            Question question = questionDAO.findById(new Integer(questionForm.getId()));
            boolean ifUpdateDate = ifUpdateQuestionDate(questionForm,question);
            question.setTitle(questionForm.getTitle());
            question.setContent(questionForm.getContent());
            question.setReference(questionForm.getReference());
            question.setAddition(questionForm.getAddition());
            question.setIsRequireLogin(questionForm.getIsRequireLogin());
            String titleAttribute = setTitleStyle(questionForm.isTitleIsBold(), questionForm.getTitleColor());
            String email = questionForm.getEmail();
            question.setEmail(email);
            String[] cities = questionForm.getCities();
            if (cities != null && cities.length > 0){
            	Set citiesSet = new HashSet();
            	for(int i = 0; i < cities.length; i++){
            		City city = new City();
            		city.setId(Integer.valueOf(cities[i]));
            		citiesSet.add(city);
            	}
            	question.setCities(citiesSet);
            }
            question.setTitleAttribute(titleAttribute);
            FormFile file = questionForm.getFile();
            String fName = "";
            boolean ifNewAddFile = false;
            if(file != null && file.getFileSize() > 0)
            {
                fName = file.getFileName();
                ifNewAddFile = true;
            }
            if(ifNewAddFile)
            {
                //delete old file and add new file
                String newFilePath = modifyUploadedFile(file,question.getFile(),errors);
                if(newFilePath != null)
                {
                    question.setFileName(fName);
                    question.setFile(newFilePath);
                }
            }
           //if(ifUpdateDate) 
           //question.setChangeDate(new Date());
           questionDAO.update(question);
           tx.commit();
        }
        catch(QaException qe)
        {
            logger.error("modify question(id="+questionForm.getId()+") QaException:"+qe);
        }
        catch(Exception e)
        {
            if(tx != null)tx.rollback();
            logger.error("modify question(id="+questionForm.getId()+") Exception:"+e);
            throw new QaException(e);
        }
        finally
        {
            HibernateSessionFactory.closeSession();  
        }
    }
    
    private boolean ifUpdateQuestionDate(QuestionForm questionForm,Question question)
    {
        boolean ifUpdate = false;
        if(!questionForm.getContent().equals(question.getContent()))
        {
            ifUpdate = true;
        }
        return ifUpdate;
    }
    
    private String modifyUploadedFile(FormFile file,String oldFilePath,ActionMessages errors) throws QaException
    {
        if(file == null)return null;
        String fileName = file.getFileName();
        if(fileName == null || fileName.length() == 0)return null;
        String newFilePath = "";
        try
        {
            if(checkIfFileExist(fileName))
            {
                errors.add("",new ActionMessage("sharedfile.exist",fileName));
                return null;
            }
            InputStream in = file.getInputStream();
            String yearMonthDayPath = checkAndBuildYearMonthDayDir();// /yyyy/mm/dd
            String dirPath = getPhisicalUploadedFileDir()+yearMonthDayPath;// /root/uploadedfile/yyyy/mm/dd
            String phisicalFile = "";
            phisicalFile = dirPath+File.separator+fileName;
            newFilePath = yearMonthDayPath+File.separator+fileName;// /yyyy/mm/dd/file.ext
            OutputStream out = new FileOutputStream(phisicalFile);
            Util.copyStream(in, out);
            in.close();
            out.close();
        }
        catch(Exception e)
        {
            errors.add("",new ActionMessage("uploadfile.failure",fileName));
            logger.error("add uploaded file into dir exception:"+e);
            throw new QaException(e);
        }
        String sharedFileDirStr = getPhisicalUploadedFileDir();
        String _oldFilePath = sharedFileDirStr+oldFilePath;
        try
        {
            File oldFile = new File(_oldFilePath);
            if(oldFile.exists())
                oldFile.delete();
        }
        catch(Exception e)
        {
            logger.error("delete uploaded file "+oldFilePath+" exception:"+e);
        }
        return newFilePath;
    }

    /**
     * change the category of the question
     * 
     * @param questionForm QuestionForm
     * @param userId Integer
     * @return
     * @throws QaException
     */
    private Question changeCategory(QuestionForm questionForm, Integer userId) throws QaException
    {
        Transaction tx = null;
        try
        {
            QuestionDAO questionDAO = new QuestionDAO();
            tx = HibernateSessionFactory.getSession().beginTransaction();
            Question question = questionDAO.findById(new Integer(questionForm.getId()));
            QuestionCategory fromCategory = question.getMrIaskCategory();
            Integer categoryId = fromCategory.getId();
            Integer categoryIdInForm = questionForm.getCatId();
            if(categoryIdInForm != categoryId)//only when the from and to are not identical
            {
                QuestionCategoryDAO questionCategoryDAO = new QuestionCategoryDAO();
                QuestionCategory toCategory = questionCategoryDAO.findById(categoryIdInForm);
                question.setMrIaskCategory(toCategory);
                MrIaskCategoryStatistics tos = toCategory.getMrIaskCategoryStatistics();
                tos.setTotal(tos.getTotal()+1);
                MrIaskCategoryStatistics froms= fromCategory.getMrIaskCategoryStatistics();
                froms.setTotal(froms.getTotal()-1);
                HibernateSessionFactory.getSession().update(fromCategory);
                HibernateSessionFactory.getSession().update(toCategory);
                questionDAO.update(question);
            }
           tx.commit();
           return question;
        }
        catch(Exception e)
        {
            if(tx != null)tx.rollback();
            throw new QaException(e);
        }
        finally
        {
            HibernateSessionFactory.closeSession();  
        }
    }

	
    private void setType(Integer id, String type, String state) throws QaException
    {
        Transaction tx = null;
        try
        {
            QuestionDAO questionDAO = new QuestionDAO();        
            tx = HibernateSessionFactory.getSession().beginTransaction();
            Question question = questionDAO.findById(id);
            if("state".equals(type))
            {
                question.setState(state);
            }else if("poll".equals(type))
            {
                question.setIsPoll(state);
            }
            questionDAO.update(question);
            tx.commit();
        }
        catch(Exception e)
        {
            if(tx != null)tx.rollback();
            throw new QaException(e);
        }
        finally
        {
            HibernateSessionFactory.closeSession();  
        }
    }
    /**
    * returns all questions
    * 
    * @param page
    * @param catId
    * @return
    */
    public List list1(int page, int pageSize, Integer catId,
    HttpServletRequest request,ActionMessages errors,UserSession us,QuestionCategory cat)
    throws QaException,SecurityException
    {
        Transaction tx = null;
        try
        {
            List list = null;
            QuestionDAO questionDAO = new QuestionDAO();
            //logger.info("page="+page+",pageSize="+pageSize);
            questionDAO.setPage(page, pageSize);
            tx = HibernateSessionFactory.getSession().beginTransaction();
            if(catId == null || catId.intValue() == 0)
            {
                //cache the questions accessed frequently
                questionDAO.setCacheable(true);
                list = questionDAO.findAll();
            }
            else
            {
                QuestionCategory questionCategory = new QuestionCategoryDAO().findById(catId);
                cat = questionCategory;
                if(userHasRightToQuestionCategory(questionCategory,us))
                {
                    request.setAttribute("questioncategory",questionCategory);
                    list = questionDAO.getAllQuestionsForAQuestionCategory(questionCategory);
                }
                else 
                {
                    errors.add("hasNoRightToCategory",new ActionMessage("user.noright"));
                    throw new SecurityException("User:"+us+" has no right to "+questionCategory);
                }
            }
            tx.commit();
            return list;
        }
        catch(SecurityException se) 
        {
            throw se;
        }
        catch(Exception e)
        {
            if(tx != null)tx.rollback();
            throw new QaException(e);
        }
        finally
        {
            HibernateSessionFactory.closeSession();  
        }
    }

    /**
    * returns all questions
    *
    * @param page
    * @param catId
    * @return
    */
    public List list(int page, int pageSize, Integer catId,
    HttpServletRequest request,ActionMessages errors,UserSession us, Integer categoryType, QuestionForm form)
    throws QaException,SecurityException
    {
        Transaction tx = null;
        try
        {
    	    List list = null;
            QuestionDAO questionDAO = new QuestionDAO();
            //logger.info("page="+page+",pageSize="+pageSize);
            questionDAO.setPage(page, pageSize);
            Integer cityId = null;
            if (form.getCities() != null){
            	cityId = Integer.valueOf(form.getCities()[0]);
            }
            tx = HibernateSessionFactory.getSession().beginTransaction();
            if(catId == null || catId.intValue() == 0)
            {
                //cache the questions accessed frequently
                questionDAO.setCacheable(true);
                list = questionDAO.findByCategoryType(categoryType, cityId);
            }
            else
            {
                QuestionCategory questionCategory = new QuestionCategoryDAO().findById(catId);
                if(userHasRightToQuestionCategory(questionCategory,us))
                {
                    request.setAttribute("questioncategory",questionCategory);
                    list = questionDAO.getAllQuestionsForAQuestionCategoryCities(questionCategory, cityId);
                }
                else
                {
                    errors.add("hasNoRightToCategory",new ActionMessage("user.noright"));
                    throw new SecurityException("User:"+us+" has no right to "+questionCategory);
                }
            }
            
            if (categoryType == 1){
            	for(Iterator it = list.iterator(); it.hasNext();){
            		Question question = (Question)it.next();
            		if (!question.getIsExpired()){
            			setExpire(question);
            		}
            	}
            }
	    tx.commit();
            return list;
	}
        catch(SecurityException se)
        {
            throw se;
        }
        catch(Exception e)
        {
            if(tx != null)tx.rollback();
            throw new QaException(e);
        }
        finally
        {
            HibernateSessionFactory.closeSession();
        }
    }

    /**
     * to check if the user has right to get list under specified QuestionCategory especially internal one
     * @param questionCategory
     * @param us
     * @return
     */
    private boolean userHasRightToQuestionCategory(QuestionCategory questionCategory,UserSession us) 
    {
        boolean hasRight = false;
        if(questionCategory == null)return false;
        if("I".equals(questionCategory.getOnlyForAdmin()))
        {
            if(us != null) 
            {
                if("1".equals(us.getType()))hasRight = true;
                else
                {
                    if(us.getIsSuper())
                    {
                        //String permissions = us.getPermissions();
                        //if(permissions != null && permissions.indexOf(questionCategory.getId()+",") >= 0)hasRight = true;
                         hasRight = true;
                    }
                }
            }
        }
        else 
        {
            hasRight = true;
        }
        return hasRight;
    }
    

    /**
     * returns all latest questions for home page(10 items)
     * 
     * @param page
     * @param catId
     * @return
     */
    public List latestList(int page, int pageSize, Integer catId,
    HttpServletRequest request,ActionMessages errors,UserSession us)
    throws QaException,SecurityException
    {
        Transaction tx = null;
        try
        {
            //UserSession us = UserSessionUtil.getUserSession(request);
            QuestionDAO questionDAO = new QuestionDAO();
            //home page
            if(us != null)questionDAO.setUserType(null);
            questionDAO.setPage(page, pageSize);
            tx = HibernateSessionFactory.getSession().beginTransaction();            
            List list = null;
            if(catId == null || catId.intValue() == 0)
            {
                list = questionDAO.findAll();
            }
            else
            {
                QuestionCategory questionCategory = new QuestionCategoryDAO().findById(catId);
                if(userHasRightToQuestionCategory(questionCategory,us))
                {
                    request.setAttribute("questioncategory",questionCategory);
                    list = questionDAO.getAllQuestionsForAQuestionCategory(questionCategory);
                }
                else 
                {
                    errors.add("hasNoRightToCategory",new ActionMessage("user.noright"));
                }                
            }
            return list;
        }
        catch(SecurityException se) 
        {
            throw se;
        }
        catch(Exception e)
        {
            if(tx != null)tx.rollback();
            logger.error("latestlist ex:"+e);
            throw new QaException(e);
        }
        finally
        {
            HibernateSessionFactory.closeSession();  
        }
    }
    /**
     * returns all recommended questions
     * 
     * @param page
     * @param catId
     * @return
     */
    public List recommendedList(int page,int pageSize, Integer catId,
    HttpServletRequest request,ActionMessages errors,UserSession us, Integer categoryType)
    throws QaException,SecurityException
    {
        Transaction tx = null;
        try
        {
            QuestionDAO questionDAO = new QuestionDAO();
            questionDAO.setPage(page, pageSize);
            List list = null;
            if(catId == null || catId.intValue() == 0)
            {
                list = questionDAO.findRecommendedAll(categoryType);
            }
            else
            {
                QuestionCategory questionCategory = new QuestionCategoryDAO().findById(catId);
                if(userHasRightToQuestionCategory(questionCategory,us))
                {
                    request.setAttribute("questioncategory",questionCategory);
                    list = questionDAO.getAllRecommendedQuestionsForAQuestionCategory(questionCategory);
                }
                else 
                {
                    errors.add("hasNoRightToCategory",new ActionMessage("user.noright"));
                    throw new SecurityException("User:"+us+" has no right to "+questionCategory);
                }
            }
            return list;
        }
        catch(SecurityException se) 
        {
            throw se;
        }
        catch(Exception e)
        {
            if(tx != null)tx.rollback();
            throw new QaException(e);
        }
        finally
        {
            HibernateSessionFactory.closeSession();  
        }
    }
    /**
     * returns all complicated questions
     * 
     * @param page
     * @param catId
     * @return
     */
    public List complicatedList(int page, int pageSize, Integer catId,
    HttpServletRequest request,ActionMessages errors,UserSession us, Integer categoryType)
    throws QaException,SecurityException
    {
        Transaction tx = null;
        try
        {
            QuestionDAO questionDAO = new QuestionDAO();
            questionDAO.setPage(page, pageSize);
            List list = null;
            if(catId == null || catId.intValue() == 0)
            {
                list = questionDAO.findComplicatedAll(categoryType);
            }
            else
            {
                QuestionCategory questionCategory = new QuestionCategoryDAO().findById(catId);
                if(userHasRightToQuestionCategory(questionCategory,us))
                {
                    request.setAttribute("questioncategory",questionCategory);
                    list = questionDAO.getAllComplicatedQuestionsForAQuestionCategory(questionCategory);
                }
                else 
                {
                    errors.add("hasNoRightToCategory",new ActionMessage("user.noright"));
                    throw new SecurityException("User:"+us+" has no right to "+questionCategory);
                }
            }
            return list;
        }
        catch(SecurityException se) 
        {
            throw se;
        }
        catch(Exception e)
        {
            if(tx != null)tx.rollback();
            throw new QaException(e);
        }
        finally
        {
            HibernateSessionFactory.closeSession();  
        }
    }

    /**
     * returns all hot questions whose answers' size is over specified number such as 2
     * 
     * @param page
     * @param catId
     * @return
     */
    public List hotList(int page, int pageSize,Integer catId,
    HttpServletRequest request,ActionMessages errors,UserSession us, Integer categoryType)
    throws QaException,SecurityException
    {
        Transaction tx = null;
        try
        {
            QuestionDAO questionDAO = new QuestionDAO();
            questionDAO.setPage(page, pageSize);
            List list = null;
            if(catId == null || catId.intValue() == 0)
            {
                list = questionDAO.findHotAll(categoryType);
            }
            else
            {
                QuestionCategory questionCategory = new QuestionCategoryDAO().findById(catId);
                if(userHasRightToQuestionCategory(questionCategory,us))
                {
                    request.setAttribute("questioncategory",questionCategory);
                    list = questionDAO.getAllHotQuestionsForAQuestionCategory(questionCategory);
                }
                else 
                {
                    errors.add("hasNoRightToCategory",new ActionMessage("user.noright"));
                    throw new SecurityException("User:"+us+" has no right to "+questionCategory);
                }
            }
            return list;
        }
        catch(SecurityException se) 
        {
            throw se;
        }
        catch(Exception e)
        {
            if(tx != null)tx.rollback();
            throw new QaException(e);
        }
        finally
        {
            HibernateSessionFactory.closeSession();  
        }
    }
    /**
     * recommend a question, if current is 2, set to 5, if 0, set to 1
     * @param questionId
     * @param errors
     * @throws QaException
     */
    public void recommend(Integer questionId,ActionMessages errors) throws QaException
    {
        Transaction tx = null;
        try
        {
            boolean ifUpdate = false;
            QuestionDAO questionDAO = new QuestionDAO();        
            tx = HibernateSessionFactory.getSession().beginTransaction();
            Question question = questionDAO.findById(questionId);
            String state = question.getState();
            if("2".equals(state))
            {
                question.setState("5");
                ifUpdate = true;
            }
            else if("0".equals(state))
            {
                question.setState("1");
                ifUpdate = true;
            }
            if(ifUpdate)
            {
                questionDAO.update(question);
                questionDAO.addScoreHistory(question.getMrIaskUser(), questionId, question.getTitle(),"recommend", "Question" + questionId +  "is recommanded");
                tx.commit();
            }
        }
        catch(Exception e)
        {
            if(tx != null)tx.rollback();
            throw new QaException(e);
        }
        finally
        {
            HibernateSessionFactory.closeSession();  
        }
    }
    /**
     * unrecommend a question, if current is 5, set to 2, if 1, set to 0
     * @param questionId
     * @param errors
     * @throws QaException
     */
    public void unrecommend(Integer questionId,ActionMessages errors) throws QaException
    {
        Transaction tx = null;
        try
        {
            boolean ifUpdate = false;
            QuestionDAO questionDAO = new QuestionDAO();        
            tx = HibernateSessionFactory.getSession().beginTransaction();
            Question question = questionDAO.findById(questionId);
            String state = question.getState();
            if("5".equals(state))
            {
                question.setState("2");
                ifUpdate = true;
            }
            else if("1".equals(state))
            {
                question.setState("0");
                ifUpdate = true;
            }
            if(ifUpdate)
            {
                questionDAO.update(question);
                questionDAO.addScoreHistory(question.getMrIaskUser(), questionId, question.getTitle(), "unrecommend", "Question" + questionId +  "is unrecommanded");
                tx.commit();
            }
        }
        catch(Exception e)
        {
            if(tx != null)tx.rollback();
            throw new QaException(e);
        }
        finally
        {
            HibernateSessionFactory.closeSession();  
        }
    }

    /**
     * complicate a question, if current state is 1, set to 5, if 0, set to 2
     * @param questionId
     * @param errors
     * @throws QaException
     */
    public void complicate(Integer questionId,ActionMessages errors) throws QaException
    {
        Transaction tx = null;
        try
        {
            boolean ifUpdate = false;
            QuestionDAO questionDAO = new QuestionDAO();        
            tx = HibernateSessionFactory.getSession().beginTransaction();
            Question question = questionDAO.findById(questionId);
            String state = question.getState();
            if("1".equals(state))
            {
                question.setState("5");
                ifUpdate = true;
            }
            else if("0".equals(state))
            {
                question.setState("2");
                ifUpdate = true;
            }
            if(ifUpdate)
            {
                questionDAO.update(question);
                tx.commit();
            }
        }
        catch(Exception e)
        {
            if(tx != null)tx.rollback();
            throw new QaException(e);
        }
        finally
        {
            HibernateSessionFactory.closeSession();  
        }
    }
    /**
     * unrecommend a question, if current is 5, set to 1, if 2, set to 0
     * @param questionId
     * @param errors
     * @throws QaException
     */
    public void uncomplicate(Integer questionId,ActionMessages errors) throws QaException
    {
        Transaction tx = null;
        try
        {
            boolean ifUpdate = false;
            QuestionDAO questionDAO = new QuestionDAO();        
            tx = HibernateSessionFactory.getSession().beginTransaction();
            Question question = questionDAO.findById(questionId);
            String state = question.getState();
            if("5".equals(state))
            {
                question.setState("1");
                ifUpdate = true;
            }
            else if("2".equals(state))
            {
                question.setState("0");
                ifUpdate = true;
            }
            if(ifUpdate)
            {
                questionDAO.update(question);
                tx.commit();
            }
        }
        catch(Exception e)
        {
            if(tx != null)tx.rollback();
            throw new QaException(e);
        }
        finally
        {
            HibernateSessionFactory.closeSession();  
        }
    }
    /**
     * if a question is locked by admin, user can not see the answer form so that
     * can not answer. the previous answers are still be displayed
     * @param questionId
     * @throws com.mr.qa.exception.QaException
     */
    public void lock(Integer questionId) throws QaException
    {
        Transaction tx = null;
        try
        {
            QuestionDAO questionDAO = new QuestionDAO();
            tx = HibernateSessionFactory.getSession().beginTransaction();
            Question question = questionDAO.findById(questionId);
            boolean isLocked = question.getIsLocked();
            if(!isLocked)
            {
                question.setIsLocked(true);
            }
            else
            {
                question.setIsLocked(false);
            }
            boolean ifUpdate = true;
            if(ifUpdate)
            {
                questionDAO.update(question);
                tx.commit();
            }
        }
        catch(Exception e)
        {
            if(tx != null)tx.rollback();
            throw new QaException(e);
        }
        finally
        {
            HibernateSessionFactory.closeSession();
        }
    }
    /**
     * if a question is marked as an activity, user can enroll by online sending
     * email to organizor.
     * If it is true, set to false; otherwise, set to true
     * @param questionId
     * @throws com.mr.qa.exception.QaException
     */
    public void setAsActivity(Integer questionId) throws QaException
    {
        Transaction tx = null;
        try
        {
            QuestionDAO questionDAO = new QuestionDAO();
            tx = HibernateSessionFactory.getSession().beginTransaction();
            Question question = questionDAO.findById(questionId);
            boolean isActivity = question.getIsActivity();
            if(!isActivity)
            {
                question.setIsActivity(true);
            }
            else
            {
                question.setIsActivity(false);
            }
            boolean ifUpdate = true;
            if(ifUpdate)
            {
                questionDAO.update(question);
                tx.commit();
            }
        }
        catch(Exception e)
        {
            if(tx != null)tx.rollback();
            throw new QaException(e);
        }
        finally
        {
            HibernateSessionFactory.closeSession();
        }
    }

    /**
     * top a question, if the question has been topped,set to untopped
     * @param questionId
     * @param topLevel 0 means to cancel all priority,1 means to top to home page,2 means to not top to home page 
     * @param errors
     * @throws QaException
     */
    private void top(Integer questionId,String topLevel,ActionMessages errors) throws QaException
    {
        Transaction tx = null;
        try
        {
            QuestionDAO questionDAO = new QuestionDAO();        
            tx = HibernateSessionFactory.getSession().beginTransaction();
            Question question = questionDAO.findById(questionId);
            if("1".equals(topLevel))
            {
                question.setIsTop(true);
                question.setIsSecondaryTop(true);
            }
            else if("2".equals(topLevel))
            {
                question.setIsTop(false);
                question.setIsSecondaryTop(true);
            }
            else if("0".equals(topLevel))
            {
                question.setIsTop(false);
                question.setIsSecondaryTop(false);
            }
            /*
            if(!question.getIsTop())
            {
                question.setIsTop(true);
            }
            else
            {
                question.setIsTop(false);
            }*/
            tx.commit();
        }
        catch(Exception e)
        {
            if(tx != null)tx.rollback();
            throw new QaException(e);
        }
        finally
        {
            HibernateSessionFactory.closeSession();  
        }
    }
    //fetch the questions on index page
    private void index(HttpServletRequest request,ActionMessages errors) throws QaException
    {
        Transaction tx = null;
        try
        {
            UserSession us = UserSessionUtil.getUserSession(request);
            QuestionDAO questionDAO = new QuestionDAO();
            questionDAO.setCacheable(true);
            QuestionCategory questionCategory = null;
            List list = null;
            tx = HibernateSessionFactory.getSession().beginTransaction();
            
            if(us != null)questionDAO.setUserType(null);            
            
            questionDAO.setPage(1, GlobalConfigs.SIZE_LATESTNEWS_HOMEPAGE+10);
            //List list = null;
            list = questionDAO.findByCategoryType(0, null);
            //QuestionCategory questionCategory = null;
             
            //right-top 1 it is removed
            
            list = filterout(list, 0);
            request.setAttribute("latestquestions",list);
            
            List lifeList = questionDAO.findByCategoryType(1, null);
            lifeList = filterout(lifeList, 1);
            request.setAttribute("latestlives",lifeList);
            
            //center-top 1 hire-ad
            questionDAO.setPage(1, GlobalConfigs.SIZE_PART_1_HOMEPAGE);
            questionCategory = new QuestionCategoryDAO().findById(47);
            list = questionDAO.getAllQuestionsForAQuestionCategory(questionCategory);
            request.setAttribute("part1",list);

            //center-top 2, MF-club
            questionDAO.setPage(1, GlobalConfigs.SIZE_PART_2_HOMEPAGE);
            questionCategory = new QuestionCategoryDAO().findById(52);
            list = questionDAO.getAllQuestionsForAQuestionCategory(questionCategory);
            request.setAttribute("part2",list);

            //center-top 3, career
            questionDAO.setPage(1, GlobalConfigs.SIZE_PART_3_HOMEPAGE);
            questionCategory = new QuestionCategoryDAO().findById(21);
            list = questionDAO.getAllQuestionsForAQuestionCategory(questionCategory);
            request.setAttribute("part3",list);
            //center-top 4,technica
            questionDAO.setPage(1, GlobalConfigs.SIZE_PART_4_HOMEPAGE);
            list = questionDAO.getAllQuestionsForAQuestionCategoryType(2, null);
            request.setAttribute("part4",list);
            
            //shared files
            SharedFileDAO sharedFileDAO = new SharedFileDAO();
            sharedFileDAO.setPage(1, GlobalConfigs.SIZE_SHAREDFILES_HOMEPAGE);
            list = sharedFileDAO.findSharedFiles();
            request.setAttribute("sharedfiles",list);
            
          //article 
            ShopArticle shopArticle = new ShopArticle();
            list = shopArticle.getAllArticlesNoZeroOrderByExchangeNoPagination();
            request.setAttribute("articles",list);
            
            /*
            request.setAttribute("hotquestions",list(1,GlobalConfigs.SIZE_HOTTESTNEWS_HOMEPAGE,21,request));
            //request.setAttribute("recommendedquestions",recommendedList(1,GlobalConfigs.SIZE_RECOMMENDEDNEWS_HOMEPAGE,catId,request
            //top 3 
            request.setAttribute("recommendedquestions",list(1,GlobalConfigs.SIZE_RECOMMENDEDNEWS_HOMEPAGE,1,request));
            //request.setAttribute("complicatedquestions",complicatedList(1,GlobalConfigs.SIZE_COMPLICATEDNEWS_HOMEPAGE,catId,request));
            //changed to enterprise recruiting in top 1
            request.setAttribute("complicatedquestions",list(1,GlobalConfigs.SIZE_COMPLICATEDNEWS_HOMEPAGE,26,request));
            */
            tx.commit();
        }
        catch(Exception e)
        {
            throw new QaException(e);
        }
        finally
        {
            HibernateSessionFactory.closeSession();  
        }
    }
    
    /**
     * filter out the questions that current date-its post date <= 48 and isTop 
     * @param list
     * @return
     */
    private List filterout(List list, int categoryType)
    {
        Iterator ite = list.iterator();
        Question question = null;
        Date curDate = new Date();
        Date questionDate = null;
        long timeDiff = 0;
        while(ite.hasNext())
        {
            question = (Question)ite.next();
            questionDate = question.getPostDate();
            timeDiff = (curDate.getTime()-questionDate.getTime())/3600000;
            if((!(timeDiff <= 48) && question.getIsTop()))
            {
                ite.remove();
            }
        }
        int size = 0;
        if(categoryType == 0){
        	size = GlobalConfigs.SIZE_LATESTNEWS_HOMEPAGE;
        }else if(categoryType == 1){
        	size = GlobalConfigs.SIZE_LATESTLIVES_HOMEPAGE;
        }
        int sizeDiff = list.size()-size;
        if(sizeDiff > 0){
            list = list.subList(0,size);
        }
        
        return list;
    }
    
    /**
     * switch the status of isExpired of an ad question
     * @param questionId
     * @throws QaException
     */
    private void switchExpired(int questionId) throws QaException
    {
        Transaction tx = null;
        try
        {
            QuestionDAO questionDAO = new QuestionDAO();        
            tx = HibernateSessionFactory.getSession().beginTransaction();
            Question question = questionDAO.findById(questionId);
            if(!question.getIsExpired())
            {
                question.setIsExpired(true);
                question.setIsTop(false);
            }
            else
            {
                question.setIsExpired(false);
            }
            tx.commit();
        }
        catch(Exception e)
        {
            if(tx != null)tx.rollback();
            throw new QaException(e);
        }
        finally
        {
            HibernateSessionFactory.closeSession();  
        }
    }

    private boolean checkIfFileExist(String fileName)
    {
        Calendar calendar= Calendar.getInstance();
        String year = ""+calendar.get(Calendar.YEAR);
        String month = ""+(calendar.get(Calendar.MONTH)+1);
        String day = ""+calendar.get(Calendar.DATE);
        String yearDirPath = getPhisicalUploadedFileDir()+File.separator+year
        +File.separator+month+File.separator+day;
        String phisicalFilePath = yearDirPath+File.separator+fileName;
        File phisicalFile = new File(phisicalFilePath);
        return phisicalFile.exists();
    }
    
    /**
     * @return the absolute path of shared file, e.g./root/sharedfile(unix)
     */
    private String getPhisicalUploadedFileDir(UploadFileType uploadFileType)
    {
    	return GlobalConfigs.WEB_PHISICAL_ROOT_LOCATION + UploadFileType.getPhysicalPath(uploadFileType);
    }
    
    private String getPhisicalUploadedFileDir()
    {
    	return getPhisicalUploadedFileDir(UploadFileType.attachment);
    }
    /*
     * return built dirs
     */
    private String checkAndBuildYearMonthDayDir()
    {
        String sharedFileDirStr = getPhisicalUploadedFileDir();
        Calendar calendar= Calendar.getInstance();
        String year = ""+calendar.get(Calendar.YEAR);
        String month = ""+(calendar.get(Calendar.MONTH)+1);
        String day = ""+calendar.get(Calendar.DATE);
        String yearDirPath = "/"+year+"/"+month+"/"+day;
        String phisicalYearDirPath = sharedFileDirStr+yearDirPath;
        File phisicalYearPathDir = new File(phisicalYearDirPath);
        if(!phisicalYearPathDir.exists())
        {
            phisicalYearPathDir.mkdirs();
        }
        return yearDirPath;
    }
    
    public String uploadImageFile(QuestionForm form, ActionMessages errors) throws QaException{
    	FormFile file = form.getImage();
    	if (file == null || file.getFileName() == null || file.getFileName().length() == 0) {
    		errors.add("error", new ActionMessage("sharedfile.file.required"));
    		return "error";
    	}
    	int size = file.getFileSize();
    	if(size > UploadFileType.getMaxSize(UploadFileType.image)){
    		errors.add("error", new ActionMessage("image.oversize"));
    		return "error";
    	}
    	String fileName = file.getFileName();
    	String ext = fileName.substring(fileName.lastIndexOf("."));
		if(ext != null && !".jpg".equalsIgnoreCase(ext) && !".gif".equalsIgnoreCase(ext) && !".png".equalsIgnoreCase(ext)){
			errors.add("error", new ActionMessage("imageheader.filename"));
			return "error";
		}
		
		InputStream is = null;
		try{
			is = file.getInputStream();
			BufferedImage bi = ImageIO.read(is);
			int width = bi.getWidth();
			if(width > GlobalConfigs.UPLOAD_IMAGE_WIDTH){
				errors.add("error", new ActionMessage("image.width", ""+GlobalConfigs.UPLOAD_IMAGE_WIDTH));
				return "error";
			}
		}catch(IOException e1){
			throw new QaException(e1);
		}finally{
			if(is != null){
				try{
					is.close();
				}catch(IOException e){
					throw new QaException(e);
				}
			}
		}
		return uploadFile(file, UploadFileType.image, errors);
    }
    
    private String setTitleStyle(boolean isBold, Integer color){
    	StringBuffer buf = new StringBuffer("");
    	if(isBold){
    		buf.append(BOLD_STYLE);
    	}
    	if(color == 1){
    		buf.append(COLOR_RED_STYLE);
    	}else if(color == 2){
    		buf.append(COLOR_BLUE_STYLE);
    	}
    	return buf.toString();
    }
    
    private void setExpire(Question question){
    	Date curDate = new Date();
    	long dif = (new Date().getTime() - question.getPostDate().getTime())/86400000;
    	if (dif > GlobalConfigs.DAYS_QUESTION_EXPIRE){
    		question.setIsExpired(true);
    	}
    }
    
    private void getAllCities(HttpServletRequest request){
    	CityDAO cityDao = new CityDAO();
        List citylist = cityDao.findAll();
        request.setAttribute("cities", citylist);
    }
}
